// 问题：JavaScript 和 TypeScript 的区别
// 1. TypeScript 强类型语言，对类型要求更加严格，JavaScript 是弱类型语言，没有类型要求 。
// 2. TypeScript 增加了接口 interface、type、泛型、void/never/any/unknown/元组/枚举 等类型；

// interface 定义对象类型
interface Person {
  readonly id: string; // 只读属性
  name: string; // 必选属性
  age?: number; // 可选属性
  [key: string]: any; // 任意属性
}
// interface定义数组类型
interface Arr {
  [index: number]: any;
}
// interface定义函数类型
interface Fn {
  (x: number, y?: number): number;
}

type Person1 = {
  readonly id: string; // 只读属性
  name: string; // 必选属性
  age?: number; // 可选属性
  [key: string]: any; // 任意属性
};

type PersonList = Person1[];

// 泛型
// function reverse(x: string | number): string | number {
//   if (typeof x === "string") {
//     return x.split("").reverse().join("");
//   } else {
//     return Number(x.toString().split("").reverse().join(""));
//   }
// }

// const a = reverse(123);
// const b = reverse("456");
// (b as string).split("");

// function reverse(x: string): string
// function reverse(x: number): number
// function reverse(x: string | number): string | number {
//   if (typeof x === "string") {
//     return x.split("").reverse().join("");
//   } else {
//     return Number(x.toString().split("").reverse().join(""));
//   }
// }

// const a = reverse(123);
// const b = reverse("456");

// 类型推论为any
// function createArr(value: any, length: number): any[] {
//   const arr: any[] = [];

//   for (let index = 0; index < length; index++) {
//     arr.push(value);
//   }

//   return arr;
// }

// const array1 = createArr(1, 10);

function createArr<T>(value: T, length: number): T[] {
  const arr: T[] = [];

  for (let index = 0; index < length; index++) {
    arr.push(value);
  }

  return arr;
}
const array1 = createArr(1, 10);

// 没有返回值，返回值类型 void
function fn1() {}

// 报错或死循环，返回值类型 never（永不存在的值）
function fn2(): never {
  throw new Error("出错了");
}

const arr = []; // 定义空数组，没有赋值和类型，那么数组内部推论为never
// arr.push(1); // 报错

let a: unknown = 123;
a = "string";
a = true;
a = {};
a = [];
(a as []).push(); // unknown类型和any类型相似，不同的是当需要使用方法时必须类型断言
(a as string).split("");

let b: any = 123;
b = "string";
b = true;
b = {};
b = [];
b.push();
b.split();

let c: number | string; // 联合类型

let d: Person & Fn; // 交叉类型（只能用于对象类型）

// 普通数组
let arr1: number[];
// 元组
let arr2: [number, string] = [123, "456"];
arr2.push(456); // 元组允许越界，越界元素必须上上述的联合类型
arr2.push("789");
// arr2.push(true); // 报错

// 枚举
enum Api {
  GetTrademarkListApi = "/trademark",
}
